home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / WILDMAT.C < prev   
C/C++ Source or Header  |  1990-06-05  |  4KB  |  133 lines

  1. /*
  2.  * @(#)wildmat.c 1.3 87/11/06    Public Domain.
  3.  *
  4. From: rs@mirror.TMC.COM (Rich Salz)
  5. Newsgroups: net.sources
  6. Subject: Small shell-style pattern matcher
  7. Message-ID: <596@mirror.TMC.COM>
  8. Date: 27 Nov 86 00:06:40 GMT
  9.  
  10. There have been several regular-expression subroutines and one or two
  11. filename-globbing routines in mod.sources.  They handle lots of
  12. complicated patterns.  This small piece of code handles the *?[]\
  13. wildcard characters the way the standard Unix(tm) shells do, with the
  14. addition that "[^.....]" is an inverse character class -- it matches
  15. any character not in the range ".....".  Read the comments for more
  16. info.
  17.  
  18. For my application, I had first ripped off a copy of the "glob" routine
  19. from within the find(1) source, but that code is bad news:  it recurses
  20. on every character in the pattern.  I'm putting this replacement in the
  21. public domain.  It's small, tight, and iterative.  Compile with -DTEST
  22. to get a test driver.  After you're convinced it works, install in
  23. whatever way is appropriate for you.
  24.  
  25. I would like to hear of bugs, but am not interested in additions; if I
  26. were, I'd use the code I mentioned above.
  27. */
  28. /*
  29. **  Do shell-style pattern matching for ?, \, [], and * characters.
  30. **  Might not be robust in face of malformed patterns; e.g., "foo[a-"
  31. **  could cause a segmentation violation.
  32. **
  33. **  Written by Rich $alz, mirror!rs, Wed Nov 26 19:03:17 EST 1986.
  34. */
  35.  
  36. /*
  37.  * Modified 6Nov87 by John Gilmore (hoptoad!gnu) to return a "match"
  38.  * if the pattern is immediately followed by a "/", as well as \0.
  39.  * This matches what "tar" does for matching whole subdirectories.
  40.  *
  41.  * The "*" code could be sped up by only recursing one level instead
  42.  * of two for each trial pattern, perhaps, and not recursing at all
  43.  * if a literal match of the next 2 chars would fail.
  44.  */
  45. #define TRUE        1
  46. #define FALSE        0
  47.  
  48.  
  49. static int
  50. Star(s, p)
  51.     register char    *s;
  52.     register char    *p;
  53. {
  54.     while (wildmat(s, p) == FALSE)
  55.     if (*++s == '\0')
  56.         return(FALSE);
  57.     return(TRUE);
  58. }
  59.  
  60.  
  61. int
  62. wildmat(s, p)
  63.     register char    *s;
  64.     register char    *p;
  65. {
  66.     register int      last;
  67.     register int      matched;
  68.     register int      reverse;
  69.  
  70.     for ( ; *p; s++, p++)
  71.     switch (*p) {
  72.         case '\\':
  73.         /* Literal match with following character; fall through. */
  74.         p++;
  75.         default:
  76.         if (*s != *p)
  77.             return(FALSE);
  78.         continue;
  79.         case '?':
  80.         /* Match anything. */
  81.         if (*s == '\0')
  82.             return(FALSE);
  83.         continue;
  84.         case '*':
  85.         /* Trailing star matches everything. */
  86.         return(*++p ? Star(s, p) : TRUE);
  87.         case '[':
  88.         /* [^....] means inverse character class. */
  89.         if (reverse = p[1] == '^')
  90.             p++;
  91.         for (last = 0400, matched = FALSE; *++p && *p != ']'; last = *p)
  92.             /* This next line requires a good C compiler. */
  93.             if (*p == '-' ? *s <= *++p && *s >= last : *s == *p)
  94.             matched = TRUE;
  95.         if (matched == reverse)
  96.             return(FALSE);
  97.         continue;
  98.     }
  99.  
  100.     /* For "tar" use, matches that end at a slash also work. --hoptoad!gnu */
  101.     return(*s == '\0' || *s == '/');
  102. }
  103.  
  104.  
  105. #ifdef    TEST
  106. #include <stdio.h>
  107.  
  108. extern char    *gets();
  109.  
  110.  
  111. main()
  112. {
  113.     char     pattern[80];
  114.     char     text[80];
  115.  
  116.     while (TRUE) {
  117.     printf("Enter pattern:  ");
  118.     if (gets(pattern) == NULL)
  119.         break;
  120.     while (TRUE) {
  121.         printf("Enter text:  ");
  122.         if (gets(text) == NULL)
  123.         exit(0);
  124.         if (text[0] == '\0')
  125.         /* Blank line; go back and get a new pattern. */
  126.         break;
  127.         printf("      %d\n", wildmat(text, pattern));
  128.     }
  129.     }
  130.     exit(0);
  131. }
  132. #endif    /* TEST */
  133.